#pragma once

#include "EventLoop.h"
#include "Poller.h"
#include <functional>
#include <memory>

namespace GiSo {

class EventLoop; // 前置声明, 避免循环依赖
class Poller;    // 前置声明, 避免循环依赖

/**
 * @brief Channel 是事件驱动模型中的基本单元，封装了一个文件描述符及其事件处理逻辑。
 *
 * 每个 Channel 对应一个文件描述符 (socket)，负责监听该文件描述符上的事件（如可读、可写等），
 * 并在事件发生时调用预先注册的回调函数进行处理。
 */
class Channel : public std::enable_shared_from_this<Channel> {
public:
    /**
     * @brief 统一事件回调类型定义。
     *
     * 事件回调函数是一个无参数、无返回值的函数对象，用于处理特定类型的事件（如读、写、关闭等）。
     */
    using EventCallback = std::function<void()>;

    /**
     * @brief Channel 类的构造函数 (私有, 仅 EventLoop 工厂方法可创建).
     *
     * @param loop  Channel 所属的 EventLoop.
     * @param fd    要封装的文件描述符.
     */
    Channel(EventLoop* loop, int fd);

    /**
     * @brief Channel 类的析构函数.
     *
     * 在析构时，确保 Channel 已从 Poller 中移除，并释放相关资源。
     */
    ~Channel();

    /**
     * @brief 设置读事件回调函数.
     *
     * 当文件描述符上有可读事件发生时，将调用此回调函数。
     *
     * @param cb 读事件回调函数.
     */
    void SetReadCallback(EventCallback cb) { m_ReadCallback = std::move(cb); }

    /**
     * @brief 设置写事件回调函数.
     *
     * 当文件描述符上有可写事件发生时，将调用此回调函数。
     *
     * @param cb 写事件回调函数.
     */
    void SetWriteCallback(EventCallback cb) { m_WriteCallback = std::move(cb); }

    /**
     * @brief 设置关闭事件回调函数.
     *
     * 当文件描述符被关闭时，将调用此回调函数。
     *
     * @param cb 关闭事件回调函数.
     */
    void SetCloseCallback(EventCallback cb) { m_CloseCallback = std::move(cb); }

    /**
     * @brief 设置错误事件回调函数.
     *
     * 当文件描述符上发生错误时，将调用此回调函数。
     *
     * @param cb 错误事件回调函数.
     */
    void SetErrorCallback(EventCallback cb) { m_ErrorCallback = std::move(cb); }

    /**
     * @brief 启用读事件监听.
     *
     * 将读事件（EPOLLIN）添加到监听列表中，并通知 Poller 更新监听状态。
     */
    void EnableReading();

    /**
     * @brief 禁用读事件监听.
     *
     * 从监听列表中移除读事件（EPOLLIN），并通知 Poller 更新监听状态。
     */
    void DisableReading();

    /**
     * @brief 启用写事件监听.
     *
     * 将写事件（EPOLLOUT）添加到监听列表中，并通知 Poller 更新监听状态。
     */
    void EnableWriting();

    /**
     * @brief 禁用写事件监听.
     *
     * 从监听列表中移除写事件（EPOLLOUT），并通知 Poller 更新监听状态。
     */
    void DisableWriting();

    /**
     * @brief 禁用所有事件监听.
     *
     * 移除所有监听事件（包括读、写等），并通知 Poller 更新监听状态。
     */
    void DisableAllEvents();

    /**
     * @brief 处理就绪事件 (由 EventLoop::loop() 通过 Poller 调用).
     *
     * 根据 Poller 返回的事件类型，调用相应的回调函数（如读、写、关闭等）。
     */
    void HandleEvent();

    /**
     * @brief 检查当前是否没有任何事件被监听.
     *
     * @return 如果没有监听任何事件，返回 true；否则返回 false.
     */
    bool IsNoneEvent() const { return m_Event == s_NoneEvent; }

    /**
     * @brief 检查当前是否正在监听读事件.
     *
     * @return 如果正在监听读事件，返回 true；否则返回 false.
     */
    bool IsReading() const { return m_Event & s_ReadEvent; }

    /**
     * @brief 检查当前是否正在监听写事件.
     *
     * @return 如果正在监听写事件，返回 true；否则返回 false.
     */
    bool IsWriting() const { return m_Event & s_WriteEvent; }

    /**
     * @brief 获取文件描述符.
     *
     * @return 文件描述符的值.
     */
    int GetFd() const { return m_Fd; }

    /**
     * @brief 获取当前监听的事件集合.
     *
     * @return 当前监听的事件集合（如 EPOLLIN、EPOLLOUT 等）.
     */
    int GetEvents() const { return m_Event; }

    /**
     * @brief 获取当前发生的事件集合.
     *
     * @return 当前发生的事件集合（如 EPOLLIN、EPOLLOUT 等）.
     */
    int GetRevents() const { return m_Revent; }

    /**
     * @brief 设置当前发生的事件集合.
     *
     * @param revt 当前发生的事件集合.
     */
    void SetRevents(int revt) { m_Revent = revt; }

    /**
     * @brief 检查当前 Channel 是否正在被 Poller 监听.
     *
     * @return 如果正在被监听，返回 true；否则返回 false.
     */
    bool IsEventHandling() const { return m_EventHandling; }

    /**
     * @brief 设置当前 Channel 是否正在被 Poller 监听.
     *
     * @param handling 如果正在被监听，设置为 true；否则设置为 false.
     */
    void SetEventHandling(bool handling) { m_EventHandling = handling; }

    /**
     * @brief 更新 Poller 中的 Channel.
     *
     * 通知 Poller 更新当前 Channel 的监听状态（如添加、修改或删除监听事件）。
     */
    void Update();

    /**
     * @brief 通过fd读取数据到
     * 
     */
    int Read(char* buf, size_t len);

    /**
     * @brief 写数据到fd
     * 
     */
    int Write(const void* data, size_t len);

    /**
     * @brief 从 Poller 中移除 Channel.
     *
     * 当 Channel 不再需要被监听时，通知 Poller 将其移除。
     */
    void Remove();

    void Close();

private:

    /**
     * @brief 处理读事件.
     *
     * 调用预先注册的读事件回调函数。
     */
    void HandleRead();

    /**
     * @brief 处理写事件.
     *
     * 调用预先注册的写事件回调函数。
     */
    void HandleWrite();

    /**
     * @brief 处理关闭事件.
     *
     * 调用预先注册的关闭事件回调函数。
     */
    void HandleClose();

    /**
     * @brief 处理错误事件.
     *
     * 调用预先注册的错误事件回调函数。
     */
    void HandleError();

    static const int s_NoneEvent; ///< 表示没有监听任何事件.
    static const int s_ReadEvent; ///< 表示监听读事件 (EPOLLIN).
    static const int s_WriteEvent; ///< 表示监听写事件 (EPOLLOUT).

    EventLoop* m_EventLoop; ///< Channel 所属的 EventLoop.

    const int m_Fd;   ///< 文件描述符.
    int m_Event;      ///< 当前监听的事件集合.
    int m_Revent;     ///< 当前发生的事件集合.

    EventCallback m_ReadCallback;   ///< 读事件回调函数.
    EventCallback m_WriteCallback;  ///< 写事件回调函数.
    EventCallback m_CloseCallback;  ///< 关闭事件回调函数.
    EventCallback m_ErrorCallback;  ///< 错误事件回调函数.

    bool m_EventHandling; ///< 标记当前 Channel 是否正在被 Poller 监听.

    friend class EventLoop; // 允许 EventLoop 访问私有函数
    friend class Poller;    // 允许 Poller 访问私有法 (如果需要)
};

} // namespace GiSo